Zig Note
Meow King January 21, 2024 Updated: February 07, 2024 #zig #noteArray and Slice
const V = @Vector(4, i32);
const value = @as(V, @splat(0)); // [0, 0, 0, 0]
- make sure
slice
not be optimized to an array pointer
var array = [_]i32{1, 2, 3, 4};
// if we use `const`, then the variable `slice` may be optimized to a array pointer
var len: usize = 3;
var slice = array[0..len];
std.debug.print("{}", .{@TypeOf(slice)});
Struct
- return a struct type from a function
const std = @import("std");
fn List(comptime T: type) type {
return struct {
const Self = @This();
items: []T,
fn length(self: Self) usize {
return self.items.len;
}
};
}
pub fn main() !void {
const int_list = List(u8);
var arr: [5]u8 = .{
1, 2, 3, 4, 5,
};
var list: int_list = .{
.items = &arr,
};
std.debug.print("list len is {}\n", .{list.length()});
}
Enum & Union
- to simulate rust
enum
can hold any type, see 标记联合
Pointer
+---------------+----------------------------------------------+
| u8 | one u8 |
| *u8 | pointer to one u8 |
| [2]u8 | two u8s |
| [*]u8 | pointer to unknown number of u8s |
| [*]const u8 | pointer to unknown number of immutable u8s |
| *[2]u8 | pointer to an array of 2 u8s |
| *const [2]u8 | pointer to an immutable array of 2 u8s |
| []u8 | slice of u8s |
| []const u8 | slice of immutable u8s |
+---------------+----------------------------------------------+
Comptime
- comptime return type
fn makeLlamas(comptime count: usize) [count]u8 {}
- inline in switch
switch (thing) {
.a => |a| special(a),
inline else => |t| normal(t),
}
Built Functions
@typeInfo(Circle).Struct.fields
@field(foo, "x"); // returns the value at foo.x
Type Coversation
As of version 0.12.0-dev.2313+bf7ebfa67
, we cannot do the following:
// if both `f` and `u` is const and is not computed from variable(`var`)(so it's like comptime_int, ...), then it will succeed
var f: f32 = 0.5;
f += 0.1;
var u: u32 = 10;
u += 1;
const r: u32 = 1 + f * u; // expect r == 5
std.debug.print("r = {}\n", .{r});
It will produce an error incompatible types: 'f32' and 'u32'
, we need to do things like this:
@as(u16, @intFromFloat(@as(f16, @floatFromInt(fz)) * spacing_ratio))
String
-
String in zig: The truth is
@TypeOf("foo") == *const [3:0]u8
const str = "El Psy Kongaroo"; // *const [15]u8 std.debug.print("{s}\n", .{str}); const str_slice: []const u8 = "El Psy Kongaroo"; std.debug.print("{s}\n", .{str_slice}); const str_slice_ptr: [*]const u8 = "El Psy Kongaroo"; const str_slice_ptr_printable: [*:0]const u8 = @ptrCast(str_slice_ptr); std.debug.print("{s}", .{str_slice_ptr_printable}); const greeting: [5]u8 = .{ 'h', 'e', 'l', 'l', 'o' }; std.debug.print("{s}\n", .{greeting}); // slice of string const slice_of_string: []const []const u8 = &.{"El", "Psy", "Kongaroo"};
-
Concat String
At Compile Time
// 1
const final_url = "https://github.com/" ++ user ++ "/reponame";
// 2
const final_url = comptime std.fmt.comptimePrint("https://github.com/{s}/reponame", .{user});
At Runtime
// 1, with allocation, use `allocPrintZ` to make sure it can interact with C freely (with `\x00` ending), see 2th below
const final_url = try std.fmt.allocPrint(alloc, "https://github.com/{s}/reponame", .{user});
defer alloc.free(final_url);
// 2, with allocation (we add `\x00` to make sure we can use it to interact with C freely. i.e. @ptrCast to `[*c]const u8`)
const s1: []const u8 = try std.mem.concatWithSentinel(allocator, u8, &.{text, "hello"}, '\x00');
// 3, with allocation
var list = ArrayList(u8).init(allocator);
defer list.deinit();
try list.append('H');
try list.append('e');
try list.append('\x00');
const s1 = list.items[0..list.items.len - 1]; // we don't need to explicitly include `\x00` in our arry, or we will print `He^@` in Zig
// 2, no allocation
var buffer = [_]u8{undefined} ** 100;
const printed = try std.fmt.bufPrint(&buffer, "https://github.com/{s}/reponame", .{user});
- use
std.fmt.bufPrint
to format string.
Design Pattern
Singleton
Global variables are singletons
see Global Variables / Singletons
Memory
fn foo() {
var foo: [200]const u8 = undefined; // memory will be erased
// correct:
// const payload: []u8 = try allocator.alloc(u8, payload_len);
const foo1: [200]const u8 = "hi"; // comptime
}
Miscellaneous
.?
==orelse unreachable
- Naming:
const @"555a" = 1;
- Use
anytype
to receive parameter of any type.fn printCircle(circle: anytype) void {
const stru = .{1, 2, 3};
std.debug.print("{}\n", .{stru.@"0"});
std.debug.print("{} {} {}\n", stru);
inline for
andinline while
- interface in zig
const Insect = union(enum) {
ant: Ant,
bee: Bee,
grasshopper: Grasshopper,
pub fn print(self: Insect) void {
switch (self) {
// All of the Ant, Bee and Grasshopprt should implement `print()` method (below `case.print()`)
inline else => |case| return case.print(),
}
}
};
- let user override default struct settings:
The following code is taken from
std.zig
, and please see the example code ofstd.log
also.
const root = @import("root");
const options_override = if (@hasDecl(root, "std_options")) root.std_options else struct {};
- When parsing JSON using functions like
std.json.parseFromSlice
,parseFromSliceLeaky
, etc.:
const Wrapper = struct {
ipv4: []u8,
address: []const u8,
endpoint: []const u8,
};
You need to defer allocator.free(Wrapper.ipv4)
afterward (it will create a new memory for holding that data if not const
).
But If you declare ipv4
field to be []const u8
, then you don't need to manually clear that memory.
- use
anytype
as function parameter - Zig will detect whether passed type suits in comptime. - pretty print structures containing string:
std.log.info("response is {}", .{std.json.fmt(response)});
see https://ziggit.dev/t/how-to-print-struct-with-strings/1597/11?u=meow_king - create custom formater for you struct
- read input: use the returned value of
stdin.readUntilDelimiterOrEof
as the result
Awesome Articles / Tutorials / Books
- Learning Zig
- Zig 语言圣经
- Zig Learning Resources
- zig 构建系统解析 - 第三部分: 三个部分都很棒。第三部分;讲述了添加软件包,添加库等操作。
- Implementing Closures and Monads in Zig
NOTE: closure see this - Code study: interface idioms/patterns in zig standard libraries
- Ziggit forum docs category
Example Library / Application
Application
- bork: A TUI chat client tailored for livecoding on Twitch.
Library
- cova: Commands, Options, Values, Arguments. A simple yet robust cross-platform command line argument parsing library for Zig.